package com.iwhalecloud.bss.kite.cucc.service.batch;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import com.iwhalecloud.bss.kite.common.util.KiteBeanUtils;
import com.iwhalecloud.bss.kite.common.util.KiteListUtils;
import com.iwhalecloud.bss.kite.common.util.KiteMapUtils;
import com.iwhalecloud.bss.kite.common.util.KiteStringUtils;
import com.iwhalecloud.bss.kite.cucc.client.api.reception.ICustReceptionService;
import com.iwhalecloud.bss.kite.cucc.client.dto.cust.CuccContextCustDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.scene.CuccCustInfoDetailDTO;
import com.iwhalecloud.bss.kite.cucc.common.constant.LocalKeyConsts;
import com.iwhalecloud.bss.kite.cucc.service.attr.LocalQuerySeqHelper;
import com.iwhalecloud.bss.kite.cucc.service.batch.attr.BatchAttrProcessorFactory;
import com.iwhalecloud.bss.kite.cucc.service.batch.attr.processor.IBatchAttrProcessor;
import com.iwhalecloud.bss.kite.dataservice.cache.AttrValueCache;
import com.iwhalecloud.bss.kite.dataservice.cache.OfferDetailCache;
import com.iwhalecloud.bss.kite.dataservice.cache.ProdAttrCache;
import com.iwhalecloud.bss.kite.dataservice.entity.spec.OfferDetail;
import com.iwhalecloud.bss.kite.dataservice.entity.spec.ProdAttr;
import com.iwhalecloud.bss.kite.event.offer.InitMainOfferEvent;
import com.iwhalecloud.bss.kite.manager.api.IOperateSceneInstService;
import com.iwhalecloud.bss.kite.manager.api.IQueryInstTemplateService;
import com.iwhalecloud.bss.kite.manager.api.IQuerySceneInstService;
import com.iwhalecloud.bss.kite.manager.dto.KiteAttrDTO;
import com.iwhalecloud.bss.kite.manager.enums.ActionType;
import com.iwhalecloud.bss.kite.manager.enums.InstType;
import com.iwhalecloud.bss.kite.manager.inst.KiteAttr;
import com.iwhalecloud.bss.kite.manager.inst.KiteOfferInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteProdInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteSceneInst;
import com.iwhalecloud.bss.kite.service.inf.accept.kitexchange.handler.AcceptScalpelUtil;
import com.iwhalecloud.bss.kite.service.scene.attr.OperateInstAttrService;
import com.iwhalecloud.bss.kite.service.scene.bo.OperateSceneOfferInstBO;
import com.ztesoft.bss.common.util.SpringUtil;

import lombok.RequiredArgsConstructor;

/**
 * @author lyx
 * @version V1.0
 * @Description:
 * @date 2021/6/21
 * @Package com.iwhalecloud.bss.kite.cucc.service.batch
 */
@Service
@RequiredArgsConstructor
public class LocalBatchAcceptBO {

    private final IQuerySceneInstService querySceneInstService;

    private final IOperateSceneInstService operateSceneInstService;

    private final BatchAttrProcessorFactory batchAttrProcessorFactory;

    private final IQueryInstTemplateService queryInstTemplateService;

    private final OperateSceneOfferInstBO operateSceneOfferInstBO;

    private final ApplicationContext applicationContext;

    public void setProdAttr(String sceneInstId, List<KiteAttr> attrs, String custId, String offerInstId, CuccContextCustDTO contextCust) {
        List<KiteAttrDTO> kiteAttrDTOs = new ArrayList<>();
        List<KiteProdInst> kiteProdInsts = querySceneInstService.listProdInstsFromOfferInst(custId, offerInstId);
        String cateId = querySceneInstService.getOfferInst(custId, offerInstId).getAttrValue("cateId");
        attrs.forEach(kiteAttr -> {
            KiteAttrDTO attrDTO = new KiteAttrDTO();
            attrDTO.setFieldName(kiteAttr.getFieldName());
            // 属性转义
            ProdAttr prodAttr = ProdAttrCache.getByAttrName(kiteProdInsts.get(0).getProdId(), kiteAttr.getFieldName());
            if (Objects.nonNull(prodAttr) && KiteStringUtils.isNotEmpty(prodAttr.getAttrId())) {
                String attrValue = AttrValueCache.getAttrValueByAttrValueName(prodAttr.getAttrId(), kiteAttr.getValue());
                if (KiteStringUtils.isNotEmpty(attrValue)) {
                    attrDTO.setValue(attrValue);
                    attrDTO.setValueDesc(kiteAttr.getValue());
                }
                else {
                    attrDTO.setValue(kiteAttr.getValue());
                }
            }
            else {
                attrDTO.setValue(kiteAttr.getValue());
            }

            kiteAttrDTOs.add(attrDTO);
        });

        if (Objects.isNull(contextCust)) {
            contextCust = getContextCust(custId);
        }

        List<KiteAttr> genKiteAttrs = new ArrayList<>();
        // 设置业务号码
        KiteAttr serialNumberAttr = new KiteAttr();
        serialNumberAttr.setFieldName("serial_number");
        String serialNumber = genSerialNumber(sceneInstId, kiteProdInsts.get(0).getProdInstId(), custId, contextCust);
        serialNumberAttr.setValue(serialNumber);
        serialNumberAttr.setValueDesc(serialNumber);
        serialNumberAttr.setShowType(LocalKeyConsts.PROD_ATTR_SHOW_TYPE_E);
        genKiteAttrs.add(serialNumberAttr);
        // 设置userId
        KiteAttr userIdAttr = new KiteAttr();
        userIdAttr.setFieldName("userInstId");
        String userId = genUserId(sceneInstId, kiteProdInsts.get(0).getProdInstId(), contextCust);
        userIdAttr.setValue(userId);
        userIdAttr.setValueDesc(userId);
        userIdAttr.setShowType(LocalKeyConsts.PROD_ATTR_SHOW_TYPE_E);
        genKiteAttrs.add(userIdAttr);

        for (KiteProdInst kiteProdInst : kiteProdInsts) {
            List<KiteAttr> kiteAttrs = KiteBeanUtils.copyPropsForList(kiteAttrDTOs, KiteAttr.class);
            specialDeal(kiteProdInst, sceneInstId, cateId, kiteAttrs);
            // 业务号码属性库表没有配置，需要传入ShowType，不然更新属性时会报错
            operateSceneInstService.setAttrs(sceneInstId, kiteProdInst.getInstType(), kiteProdInst.getProdInstId(), genKiteAttrs);
//            operateSceneInstService
//                .setAttrValues(sceneInstId, kiteProdInst.getInstType(), kiteProdInst.getProdInstId(), kiteAttrDTOs);
            // 设置属性时需要联动
            SpringUtil.getBean(OperateInstAttrService.class)
                .setListAttrValue(kiteProdInst, kiteAttrs, sceneInstId, null);
            kiteAttrDTOs.forEach(kiteAttrDTO -> {
                IBatchAttrProcessor batchAttrProcessor = batchAttrProcessorFactory
                    .getBatchAttrProcessor(kiteAttrDTO.getFieldName(), kiteProdInst.getProdId());
                if (Objects.nonNull(batchAttrProcessor)) {
                    batchAttrProcessor.process(kiteAttrDTO, kiteProdInst, sceneInstId, custId);
                }
            });
        }
    }

    public void setProdAttrUserInfo(String sceneInstId, String custId, String offerInstId, CuccContextCustDTO contextCust) {
        if (Objects.isNull(contextCust)) {
            contextCust = getContextCust(custId);
        }
        List<KiteProdInst> kiteProdInsts = querySceneInstService.listProdInstsFromOfferInst(custId, offerInstId);
        List<KiteAttr> genKiteAttrs = new ArrayList<>();
        // 设置业务号码
        KiteAttr serialNumberAttr = new KiteAttr();
        serialNumberAttr.setFieldName("serial_number");
        String serialNumber = genSerialNumber(sceneInstId, kiteProdInsts.get(0).getProdInstId(), custId, contextCust);
        serialNumberAttr.setValue(serialNumber);
        serialNumberAttr.setValueDesc(serialNumber);
        serialNumberAttr.setShowType(LocalKeyConsts.PROD_ATTR_SHOW_TYPE_E);
        genKiteAttrs.add(serialNumberAttr);
        // 设置userId
        KiteAttr userIdAttr = new KiteAttr();
        userIdAttr.setFieldName("userInstId");
        String userId = genUserId(sceneInstId, kiteProdInsts.get(0).getProdInstId(), contextCust);
        userIdAttr.setValue(userId);
        userIdAttr.setValueDesc(userId);
        userIdAttr.setShowType(LocalKeyConsts.PROD_ATTR_SHOW_TYPE_E);
        genKiteAttrs.add(userIdAttr);
        // 业务号码属性库表没有配置，需要传入ShowType，不然更新属性时会报错
        operateSceneInstService.setAttrs(sceneInstId, kiteProdInsts.get(0).getInstType(), kiteProdInsts.get(0).getProdInstId(), genKiteAttrs);
    }

    private void specialDeal(KiteProdInst kiteProdInst, String sceneInstId, String cateId, List<KiteAttr> kiteAttrs) {
        // 是否外省发起 置灰
        KiteAttr kiteAttr = kiteProdInst.getAttr("2_0000018");
        if (Objects.isNull(kiteAttr)) {
            return;
        }
        kiteAttr.setIsEdit("F");
        operateSceneInstService.setAttr(sceneInstId, kiteProdInst.getInstType(), kiteProdInst.getInstId(), kiteAttr);
        // mv设置属性需要把“接入带宽”提前
        if (KiteStringUtils.equals(cateId, "2004017")) {
            kiteAttrs.sort(Comparator.comparing(attr -> {
                if (KiteStringUtils.equals(attr.getFieldName(), "2_0000164")) {
                    return 0;
                } else {
                    return 1;
                }
            }));
        }
    }

    public CuccContextCustDTO getContextCust(String custId) {
        CuccContextCustDTO contextCust = new CuccContextCustDTO();
        ICustReceptionService custReceptionService = SpringUtil.getBean(ICustReceptionService.class);
        CuccCustInfoDetailDTO cuccCustInfoDTO = custReceptionService.getCustomerInfoNew(custId);
        if (Objects.nonNull(cuccCustInfoDTO)) {
            KiteBeanUtils.copyProperties(cuccCustInfoDTO, contextCust);
            contextCust.setLanId(cuccCustInfoDTO.getCityCode());
            contextCust.setRegionId(cuccCustInfoDTO.getBcityCode());
            contextCust.setCustType(cuccCustInfoDTO.getCustClassType());
            contextCust.setCbssId(cuccCustInfoDTO.getCustId());
        }
        return contextCust;
    }

    /**
     * 生成业务号码
     *
     * @param sceneInstId
     * @param custId
     * @return
     */
    private String genSerialNumber(String sceneInstId, String custId, CuccContextCustDTO contextCust) {
        Map<String, String> inParam = new HashMap<>();
        inParam.put("SEQ_TYPE", "SERIAL_NUMBER");
        inParam.put("SYS_TYPE", "1");
        inParam.put("SYS_SOURCE", "");
        String seq = LocalQuerySeqHelper.getSeqBySeqType(inParam, sceneInstId, contextCust);
        if (KiteStringUtils.isEmpty(seq)) {
            seq = LocalKeyConsts.EMPTY_SERIAL_NUMBER;
        }
        return seq;
    }

    /**
     * 生成业务号码
     *
     * @param sceneInstId
     * @param custId
     * @return
     */
    private String genSerialNumber(String sceneInstId, String prodInstId, String custId, CuccContextCustDTO contextCust) {
        Map<String, String> inParam = new HashMap<>();
        inParam.put("SEQ_TYPE", "SERIAL_NUMBER");
        inParam.put("SYS_TYPE", "1");
        inParam.put("SYS_SOURCE", "");
        String seq = LocalQuerySeqHelper.getSeqBySeqType(inParam, sceneInstId, prodInstId, contextCust);
        if (KiteStringUtils.isEmpty(seq)) {
            seq = LocalKeyConsts.EMPTY_SERIAL_NUMBER;
        }
        return seq;
    }

    private String genUserId(String sceneInstId, CuccContextCustDTO custDTO) {
        Map<String, String> inParam = new HashMap<>();
        inParam.put("SEQ_TYPE", "USER_ID");
        inParam.put("SYS_TYPE", "1");
        inParam.put("SYS_SOURCE", "");
        return LocalQuerySeqHelper.getSeqBySeqType(inParam, sceneInstId, custDTO);
    }

    private String genUserId(String sceneInstId, String prodInstId, CuccContextCustDTO custDTO) {
        Map<String, String> inParam = new HashMap<>();
        inParam.put("SEQ_TYPE", "USER_ID");
        inParam.put("SYS_TYPE", "1");
        inParam.put("SYS_SOURCE", "");
        return LocalQuerySeqHelper.getSeqBySeqType(inParam, sceneInstId, prodInstId, custDTO);
    }

    public String addOfferInst(String sceneInstId, KiteSceneInst sceneInst, String provinceNbr, String custId,
                                String offerId) {
        KiteOfferInst offerInst = queryInstTemplateService.getOfferInst(offerId, provinceNbr);
        // 判断实例模版是否存在
        if (offerInst == null) {
            offerInst = operateSceneOfferInstBO
                .initKiteOfferInst(offerId, custId, InstType.MAIN_OFFER_INST, provinceNbr);
        }
        AcceptScalpelUtil.replaceInstId(offerInst, null);
        offerInst.setActionType(ActionType.A);
        String offerInstId = operateSceneInstService.addMainOfferInst(sceneInstId, offerInst);

        // 获取明细以发布新增销售品实例事件
        List<String> offerDetailIds = new ArrayList<>();
        List<OfferDetail> offerDetails = OfferDetailCache.get(offerId);
        if (KiteListUtils.isNotEmpty(offerDetails)) {
            offerDetailIds = offerDetails.stream().map(OfferDetail::getDetailId).collect(Collectors.toList());
        }
        InitMainOfferEvent initMainOfferEvent = new InitMainOfferEvent(this, custId, sceneInst.getStaffId());
        initMainOfferEvent.setOfferId(offerId);
        initMainOfferEvent.setParentInstId(offerInstId);
        initMainOfferEvent.setSceneInstId(sceneInstId);
        initMainOfferEvent.setDetailIds(offerDetailIds);
        applicationContext.publishEvent(initMainOfferEvent);
        return offerInstId;
    }

    public void specialDealSignAttr(KiteProdInst kiteProdInst, String sceneInstId, String serialNumber) {
        // 是否外省发起 置灰
        KiteAttr kiteAttr = kiteProdInst.getAttr("2_0000018");
        if (Objects.isNull(kiteAttr)) {
            return;
        }
        kiteAttr.setIsEdit("F");
        operateSceneInstService.setAttr(sceneInstId, kiteProdInst.getInstType(), kiteProdInst.getInstId(), kiteAttr);
        // 设置业务号码
        KiteAttr serialNumberAttr = new KiteAttr();
        serialNumberAttr.setFieldName("serial_number");
        serialNumberAttr.setValue(serialNumber);
        serialNumberAttr.setValueDesc(serialNumber);
        serialNumberAttr.setShowType(LocalKeyConsts.PROD_ATTR_SHOW_TYPE_E);
        operateSceneInstService.setAttr(sceneInstId, kiteProdInst.getInstType(), kiteProdInst.getInstId(), serialNumberAttr);

        Map<String, String> instSerialNumberMap = querySceneInstService.getExtParameterValue(sceneInstId, "instSerialNumberMap");
        if (KiteMapUtils.isNotEmpty(instSerialNumberMap)) {
            instSerialNumberMap.put(kiteProdInst.getProdInstId(), serialNumber);
            operateSceneInstService.putExtParameter(sceneInstId, "instSerialNumberMap", instSerialNumberMap);
        }
    }
}
